package com.vcg.vdam.testbeandefinitioHttpApiInvoke;

import com.vcg.vdam.annotation.YangxingAnnotation;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.lang.Nullable;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Set;

/**
 * scan the given basePackages and register bean of includeAnn-annotated interfaces' implementation that HttpProxyBeanFactory generated
 *
 * @author huangxuyang
 * date 2018/11/1
 */
public class ClassPathHttpApiScanner  extends ClassPathBeanDefinitionScanner{
    private static final String HTTP_API_PREFIX = "$HttpApi$";
    private Class<? extends FactoryBean> factoryBean;
    private Class<? extends Annotation> includeAnn;
    private BeanDefinitionRegistry registry;

    public ClassPathHttpApiScanner(BeanDefinitionRegistry registry) {
        //不使用默认的过滤器；用自己设置的
        super(registry, false);
        this.registry = registry;
        addIncludeFilter(new AnnotationTypeFilter(YangxingAnnotation.class));
    }

    public ClassPathHttpApiScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
        super(registry, useDefaultFilters);
    }

    public ClassPathHttpApiScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) {
        super(registry, useDefaultFilters, environment);
    }

    public ClassPathHttpApiScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) {
        super(registry, useDefaultFilters, environment, resourceLoader);
    }


    @Override
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);

        if (beanDefinitions.isEmpty()) {
            logger.warn("No " + includeAnn.getSimpleName() + " was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
        }
        return beanDefinitions;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
    }

    /**
     * {@inheritDoc}
     */
    //@Override
    //protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) {
    //    // Sometimes, the package scan will be conflicted with MyBatis
    //    // so the existing is not the expected one, we remove it.
    //    if (this.registry.containsBeanDefinition(beanName)) {
    //        // an HttpApi bean exists, we ignore the others.
    //        if (isHttpApiBean(beanName)) {
    //            logger.info("an HttpApi bean [" + beanName + "] exists, we ignore the others");
    //            return false;
    //        }
    //        logger.warn("an not HttpApi bean named [" + beanName + "] exists, we remove it, so that we can generate a new bean.");
    //        registry.removeBeanDefinition(beanName);
    //    }
    //    if (super.checkCandidate(beanName, beanDefinition)) {
    //        return true;
    //    } else {
    //        logger.warn("Skipping " + factoryBean.getSimpleName() + " with name '" + beanName
    //                + "' and '" + beanDefinition.getBeanClassName() + "' interface"
    //                + ". Bean already defined with the same name!");
    //        return false;
    //    }
    //}
    //
    //private boolean isHttpApiBean(String beanName) {
    //    if (registry instanceof DefaultListableBeanFactory) {
    //        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) registry;
    //        return beanFactory.containsBean(beanName) && beanFactory.getBean(beanName).toString().startsWith(HTTP_API_PREFIX);
    //    }
    //    return false;
    //}

    /**
     * registry the bean with FactoryBean
     */
    @Override
    protected void registerBeanDefinition(BeanDefinitionHolder holder, BeanDefinitionRegistry registry) {

        ////BeanDefinition beanDefinition = new RootBeanDefinition();
        //GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        //beanDefinition.getPropertyValues().add("interfaceClass", Order.class);
        //beanDefinition.setBeanClass(HttpApiProxyFactoryBean.class);
        //registry.registerBeanDefinition("order",beanDefinition);

        //GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();
        //if (logger.isDebugEnabled()) {
        //    logger.debug(includeAnn.getSimpleName() + ": Bean with name '" + holder.getBeanName()
        //            + "' and '" + definition.getBeanClassName() + "' interface");
        //}
        //if (logger.isDebugEnabled()) {
        //    logger.debug("Enabling autowire by type for " + factoryBean.getSimpleName() + " with name '" + holder.getBeanName() + "'.");
        //}
        //definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
        //// 需要被代理的接口 the interface
        //definition.getPropertyValues().add("interfaceClass", definition.getBeanClassName());
        //// 配置项
        //definition.getPropertyValues().add("propertyResolver", propertyResolver);
        //if (requestor != null) {
        //    definition.getPropertyValues().add("requestor", requestor);
        //}
        //if (requestPreprocessor != null) {
        //    definition.getPropertyValues().add("requestPreprocessor", requestPreprocessor);
        //}
        //if (responseProcessor != null) {
        //    definition.getPropertyValues().add("responseProcessor", responseProcessor);
        //}
        //// 获取bean名，注意：获取 BeanName 要在setBeanClass之前，否则BeanName就会被覆盖
        //// caution! we nned to getBeanName first before setBeanClass
        //String beanName = holder.getBeanName();
        //// 将BeanClass设置成Bean工厂
        //definition.setBeanClass(factoryBean);
        //// 注册Bean
        //registry.registerBeanDefinition(beanName, definition);
    }

}
